const crypto = require('crypto');

/**
 * 生成盐值
 * @param {number} length 盐值长度
 * @returns {string} 盐值
 */
const generateSalt = (length = 16) => {
  return crypto.randomBytes(length).toString('hex');
};

/**
 * 使用PBKDF2加密密码
 * @param {string} password 原始密码
 * @param {string} salt 盐值
 * @returns {string} 加密后的密码
 */
const hashPasswordWithSalt = (password, salt) => {
  return crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex');
};

/**
 * 加密密码
 * @param {string} password 原始密码
 * @returns {Promise<string>} 加密后的密码（包含盐值）
 */
const hashPassword = async (password) => {
  try {
    const salt = generateSalt();
    const hashedPassword = hashPasswordWithSalt(password, salt);
    // 将盐值和加密密码组合存储
    return `${salt}:${hashedPassword}`;
  } catch (error) {
    throw new Error(`密码加密失败: ${error.message}`);
  }
};

/**
 * 验证密码
 * @param {string} password 原始密码
 * @param {string} hashedPassword 存储的加密密码
 * @returns {Promise<boolean>} 密码是否匹配
 */
const comparePassword = async (password, hashedPassword) => {
  try {
    // 分离盐值和密码哈希
    const [salt, hash] = hashedPassword.split(':');
    if (!salt || !hash) {
      return false;
    }
    
    // 使用相同的盐值加密输入密码
    const hashToCompare = hashPasswordWithSalt(password, salt);
    
    // 使用安全的比较方法
    return crypto.timingSafeEqual(
      Buffer.from(hash, 'hex'),
      Buffer.from(hashToCompare, 'hex')
    );
  } catch (error) {
    console.error('密码验证错误:', error);
    return false;
  }
};

/**
 * 生成随机令牌
 * @param {number} length 令牌长度
 * @returns {string} 随机令牌
 */
const generateToken = (length = 32) => {
  return crypto.randomBytes(length).toString('hex');
};

/**
 * 生成简单的JWT风格令牌（仅用于演示，生产环境建议使用专业的JWT库）
 * @param {object} payload 载荷数据
 * @param {string} secret 密钥
 * @returns {string} 令牌
 */
const generateSimpleToken = (payload, secret = process.env.JWT_SECRET || 'default-secret') => {
  const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
  const payloadBase64 = Buffer.from(JSON.stringify({
    ...payload,
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + (24 * 60 * 60) // 24小时过期
  })).toString('base64url');
  
  const signature = crypto
    .createHmac('sha256', secret)
    .update(`${header}.${payloadBase64}`)
    .digest('base64url');
  
  return `${header}.${payloadBase64}.${signature}`;
};

/**
 * 验证简单令牌
 * @param {string} token 令牌
 * @param {string} secret 密钥
 * @returns {object|null} 解码后的载荷或null
 */
const verifySimpleToken = (token, secret = process.env.JWT_SECRET || 'default-secret') => {
  try {
    const parts = token.split('.');
    if (parts.length !== 3) {
      return null;
    }
    
    const [header, payload, signature] = parts;
    
    // 验证签名
    const expectedSignature = crypto
      .createHmac('sha256', secret)
      .update(`${header}.${payload}`)
      .digest('base64url');
    
    if (signature !== expectedSignature) {
      return null;
    }
    
    // 解码载荷
    const decodedPayload = JSON.parse(Buffer.from(payload, 'base64url').toString());
    
    // 检查过期时间
    if (decodedPayload.exp && decodedPayload.exp < Math.floor(Date.now() / 1000)) {
      return null;
    }
    
    return decodedPayload;
  } catch (error) {
    console.error('令牌验证错误:', error);
    return null;
  }
};

module.exports = {
  hashPassword,
  comparePassword,
  generateToken,
  generateSimpleToken,
  verifySimpleToken
}; 